home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ProcessShape.c
-
- Contains: QuickDraw GX to PostScript conversion code.
-
- Version: Technology: Quickdraw GX 1.1.x
-
- Copyright: © 1991-1997 by Apple Computer, Inc., all rights reserved.
- */
-
- #include "GXToPSBuildConfig.h"
-
- #include <GXGraphics.h>
- #include <GXExceptions.h>
- #include "GXGraphicsPriv.h"
-
- #include "ShapeUtilities.h"
-
- #include "OffscreenLibrary.h"
- #include "ProcessShape.h"
-
- #ifdef GraphicsScript
-
- #include <stdio.h>
- #include <FixMath.h>
-
- #endif
-
- /*-------------------------------------------------------------------------------
-
- TMTestMinMode
-
- this call tests for min mode which is useful for indexed bitmaps.
-
- -------------------------------------------------------------------------------*/
- static Boolean TMTestMinMode( gxInk shink )
- {
- gxTransferMode shmode;
- Boolean result;
-
- short count;
-
- result = true; // assume that the transfer mode is min
-
- GXGetInkTransfer( shink, &shmode );
-
- if( count = TMGetSpaceComponentCount( shmode.space ) )
- {
- gxTransferComponent *trc = shmode.component;
-
- do
- {
- // there are two possible representations of or mode
- // one is gxCopy mode where ->sourceMinimum == ->sourceMaximum
- // and the other is
- // gxMinimum and ->sourceMinimum == 0 and ->sourceMaximum == 0xFFFF
-
- if( ( trc->mode == gxMinimumMode &&
- trc->sourceMinimum == 0 &&
- trc->sourceMaximum == 0xFFFF ) &&
- ( trc->deviceMinimum == 0x0000 &&
- trc->clampMinimum == 0x0000 &&
- trc->deviceMaximum == 0xFFFF &&
- trc->clampMaximum == 0xFFFF ) )
- {
- // do nothing; we have what we want
- }
- else
- {
- result = false;
- break;
- }
-
- trc += 1;
-
- } while( 0 < --count );
- }
-
- return( result );
-
- }
- /*-------------------------------------------------------------------------------
-
- TMResolveColorSetOr
-
- this routine computes what the correct value is for a transfer mode that
- simulates or mode.
-
- -------------------------------------------------------------------------------*/
- static gxColor *TMResolveColorSetOr( gxColor *colorPtr, gxBitmap *bitsPtr, gxInk shInk )
- {
- gxTransferMode shmode;
- gxInk tempInk = GXNewInk();
-
- colorPtr->space = bitsPtr->space;
- colorPtr->profile = bitsPtr->profile;
-
- check( bitsPtr->space == gxIndexedSpace );
-
- colorPtr->element.indexed.set = bitsPtr->set;
-
- GXGetInkTransfer( shInk, &shmode );
- GXSetInkTransfer( tempInk, &shmode );
-
- colorPtr->element.indexed.index = shmode.component[ 0 ].sourceMinimum;
-
- GXSetInkColor( tempInk, colorPtr );
- GXCombineColor( colorPtr, tempInk );
-
- GXConvertColor( colorPtr, gxRGBSpace, nil, nil );
-
- GXDisposeInk( tempInk );
- return( colorPtr );
- }
- /*-------------------------------------------------------------------------------
-
- TMResolveOrModeBitmap
-
- this routine takes a shape which has a transfer mode which was derived
- from quickdraw or mode and makes one that will render correctly even when
- halftone to a raster device.
-
- -------------------------------------------------------------------------------*/
- static gxShape TMResolveOrModeBitmap( gxShape sh )
- {
- gxShape sh2 = GXNewShape( gxFullType );
- gxShapeType cliptype;
-
- gxMapping map;
- gxBitmap bits;
- gxPoint where;
-
- gxTransform xform;
-
- gxColor shcolor;
- gxColorProfile profile;
-
- xform = GXGetShapeTransform( sh );
-
- check( GXGetShapeType( sh ) == gxBitmapType );
-
- GXGetBitmap( sh, &bits, &where );
-
- check( bits.pixelSize == 1 );
-
- if( profile = bits.profile )
- {
- GXCloneColorProfile( profile );
- bits.profile = nil;
-
- // clips can't have profiles
-
- GXSetBitmap( sh, &bits, &where );
- }
-
- cliptype = GetTransformClipType( xform );
-
- if( cliptype == gxRectangleType )
- {
- gxShape clip;
- gxRectangle clipbox;
- gxRectangle testbox;
-
- // check to see if we can ignore the clip
-
- clip = GXGetTransformClip( xform );
- GXGetRectangle( clip, &clipbox );
- GXDisposeShape( clip );
-
- testbox.left = where.x;
- testbox.top = where.y;
- testbox.right = testbox.left + ff( bits.width );
- testbox.bottom = testbox.top + ff( bits.height );
-
- if( GXContainsRectangle( &clipbox, &testbox ) )
- cliptype = gxFullType;
- }
-
- if( cliptype == gxFullType )
- {
- GXGetShapeMapping( sh, &map );
- GXSetShapeMapping( sh2, &map );
- }
-
- GXSetShapeClip( sh2, sh ); // ## does this take into account the position ?
-
- check( GetTransformClipType( GXGetShapeTransform( sh2 ) ) == gxBitmapType );
-
- // here is the hard part -- we need to figure out what color to make this shape
-
- (void) TMResolveColorSetOr( &shcolor, &bits, GXGetShapeInk( sh ) );
-
- shcolor.profile = profile;
-
- GXSetShapeColor( sh2, &shcolor );
-
- if( profile ) GXDisposeColorProfile( profile );
-
- if( cliptype != gxFullType )
- {
- gxShape p;
-
- p = GXNewPicture( 1, &sh2, nil, nil, nil );
- GXDisposeShape( sh2 );
-
- check( GXGetShapeOwners( sh2 ) == 1 );
-
- GXSetShapeTransform( p, xform );
-
- sh2 = p;
- }
-
- check( GXGetShapeOwners( sh2 ) == 1 );
-
- return( sh2 );
- }
- /*-------------------------------------------------------------------------------
-
- TMAdjustOffscreenDevice
-
- this routine adjusts the offscreen device so that patterns draw
- correctly.
-
- -------------------------------------------------------------------------------*/
- static void TMAdjustOffscreenDevice( offscreen *os, gxPoint *wherePtr )
- {
- gxMapping map;
-
- GXGetViewDeviceMapping( os->device, &map );
- MoveMapping( &map, -wherePtr->x, -wherePtr->y );
- GXSetViewDeviceMapping( os->device, &map );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMGetShapeBounds
-
- this routine gets the global bounding box for a shape
-
- -------------------------------------------------------------------------------*/
- void TMGetShapeBounds( gxRectangle *shbboxPtr, gxShape sh, TShapeStack *stackPtr,
- TBBoxParam *bpptr )
- {
- gxRectangle emptybox = { 0, 0, 0, 0 };
- gxRectangle fullbox = { 0x80000000, 0x80000000, 0x7FFFFFFF, 0x7FFFFFFF };
-
- gxRectangle shbbox;
-
- gxShapeType shType;
-
- // next we look at the fill
-
- shType = GXGetShapeType( sh );
-
- // there are certain shapes that get treated especially
-
- if( shType == gxPictureType )
- {
- TShapeStack stack;
- OSErr status;
-
- shbbox = emptybox; // we start with an empty rectangle and then add the bbox's
- // for each of the shapes in the picture
- nrequire( status = TMNewStack( &stack ), MakeStackFailed );
-
- status = TMPushShape( &stack, sh ); // the picture shape
-
- for(;;)
- {
- gxShape sh2;
-
- gxRectangle sh2bbox;
-
- sh2 = TMNextShape( &stack );
-
- if( sh2 )
- {
- TMGetShapeBounds( &sh2bbox, sh2, &stack, bpptr );
-
- if( emptyrectangle( &shbbox ) )
- shbbox = sh2bbox;
- else
- GXUnionRectangle( &shbbox, &shbbox, &sh2bbox );
-
- TMFreeShape( &stack );
- }
- else
- break;
- }
-
- // dispose of the stack
-
- TMDisposeStack( &stack );
- }
- else if( shType == gxFullType )
- {
- shbbox = bpptr->pagebounds;
- }
- else
- {
- gxMapping themap;
- gxShapeFill shFill;
-
- switch( shFill = GXGetShapeFill( sh ) )
- {
- case gxNoFill:
- shbbox = emptybox; goto skipMappingComputation;
- break;
-
- case gxOpenFrameFill:
- case gxClosedFrameFill:
- case gxEvenOddFill:
- case gxWindingFill:
- GXGetShapeLocalBounds( sh, &shbbox );
-
- // for text shapes, we give the bounds a bit of slop due to non-linear scaling
- if( (shFill < gxEvenOddFill && GXGetShapePen( sh ) == 0) || shType == gxTextType || shType == gxGlyphType || shType == gxLayoutType )
- {
- shbbox.left -= bpptr->pixelsize.x;
- shbbox.top -= bpptr->pixelsize.y;
- shbbox.right += bpptr->pixelsize.x;
- shbbox.bottom += bpptr->pixelsize.y;
- }
- break;
-
- case gxInverseFill:
- shbbox = bpptr->pagebounds;
- break;
- }
- if( ! emptyrectangle( &shbbox ) )
- {
- gxTransform *trptr;
- long indx;
-
- gxPoint corners[ 4 ];
-
- // the next loop concatates the clips and mapping for the shapes going up
- // the picture hierachy. note that because the first clip and mapping come
- // from the shape we do those first and then work backwards through the stack
-
- if( stackPtr != nil )
- {
- check( stackPtr->tr.top <= stackPtr->tr.mark );
-
- if( 0 <= ( indx = ( stackPtr->tr.mark - stackPtr->tr.top ) - 1 ) )
- {
- HLock((Handle) stackPtr->tr.list );
-
- trptr = & (* stackPtr->tr.list)[ stackPtr->tr.mark - 1 ];
- }
- }
- else
- {
- indx = -1;
- }
-
- for(;;)
- {
- // now we look in the shape stack and get the next transform and the
- // next clip that will be applied the next time through
-
- if( ( 0 <= indx ) && ( ! emptyrectangle( &shbbox ) ) )
- {
- (void) GXGetTransformMapping( *trptr, &themap );
-
- trptr -= 1; // advance (backwards) the mark and counter
- indx -= 1;
- }
- else break; // we are done
-
- // we take the rectangle after it has been clipped and mapped it through the
- // transform. note that because the transform can apply rotation and
- // perspective we actually need to map each of the four corners of the
- // rectangle and not just the opposite corners of the rectangle
-
- TMBoundsToPoints( corners, &shbbox );
- MapPoints( &themap, 4, corners );
- TMPointsToBounds( &shbbox, corners );
- }
-
- if( stackPtr != nil ) HUnlock((Handle) stackPtr->tr.list );
- }
- }
-
- // before we set the rectangle we need to make sure that the rectangle that we have
- // does not overflow the pagebounds that we were given
-
- skipMappingComputation:
-
- if( ! emptyrectangle( &shbbox ) )
- GXIntersectRectangle( &shbbox, &shbbox, &( bpptr->pagebounds ) ); // force the bounds
-
- MakeStackFailed:
-
- *shbboxPtr = shbbox;
- }
-
- /*-------------------------------------------------------------------------------
-
- TMNewStack
-
- this routine creates a stack for picture references
-
- -------------------------------------------------------------------------------*/
-
- OSErr TMNewStack( TShapeStack *stackPtr )
- {
- OSErr status;
-
- stackPtr->mark = 0;
- stackPtr->tr.top = 0;
- stackPtr->tr.mark = 0;
- stackPtr->tr.seed = 0;
- stackPtr->index = 0;
-
- stackPtr->newstyle = stackPtr->savestyle = nil;
- stackPtr->newink = stackPtr->saveink = nil;
- stackPtr->newtransform = stackPtr->savetransform = nil;
-
- stackPtr->stack = ( TShapeNMark **) NewHandle( kStackListIncrement * sizeof( TShapeNMark ) );
- nrequire( status = MemError(), ShapeStackFailed );
-
- stackPtr->tr.list = ( gxTransform ** ) NewHandle( kStackListIncrement * sizeof( gxTransform ) );
- nrequire( status = MemError(), TransformStackFailed );
-
- stackPtr->count = kStackListIncrement;
- stackPtr->tr.count = kStackListIncrement;
-
- GXIgnoreGraphicsNotice( shape_already_in_primitive_form );
-
- return( noErr );
-
- DisposeHandle((Handle) stackPtr->tr.list );
-
- TransformStackFailed:
- DisposeHandle((Handle) stackPtr->stack );
-
- ShapeStackFailed:
- return( status );
- }
- /*-------------------------------------------------------------------------------
-
- TMDisposeStack
-
- this routine disposes of a stack of pictures and references.
-
- -------------------------------------------------------------------------------*/
-
- void TMDisposeStack( TShapeStack *stackPtr )
- {
- check( stackPtr->mark == 0 );
- check( stackPtr->tr.top == 0 );
-
- DisposeHandle((Handle) stackPtr->stack );
- stackPtr->mark = 0;
- stackPtr->count = 0;
-
- if( 0 < stackPtr->tr.mark )
- {
- short indx;
- gxTransform *trptr;
-
-
- indx = stackPtr->tr.mark - 1;
-
- HLock((Handle) stackPtr->tr.list );
-
- trptr = & (* stackPtr->tr.list)[ 0 ];
-
- for( ; indx >= 0; --indx )
- {
- GXDisposeTransform( *trptr++ );
- }
-
- HUnlock((Handle) stackPtr->tr.list );
- }
-
- DisposeHandle((Handle) stackPtr->tr.list );
-
- stackPtr->tr.mark = 0;
- stackPtr->tr.count = 0;
-
- GXPopGraphicsNotice( ); // pop the notices from TMNewStack
- }
-
- /*-------------------------------------------------------------------------------
-
- TMPushShape
-
- this routine adds a shape and picture to the stack
-
- -------------------------------------------------------------------------------*/
-
- OSErr TMPushShape( TShapeStack *stackPtr, gxShape sh )
- {
- OSErr status = noErr;
-
- TShapeNMark *smptr;
- long count;
-
- // check to see if we have enough room to push the shape
-
- if( stackPtr->count <= stackPtr->mark )
- {
- // we need to grow the stack
-
- SetHandleSize((Handle) stackPtr->stack, sizeof( TShapeNMark ) *
- ( stackPtr->count + kStackListIncrement ) );
- nrequire( status = MemError(), GrowStackFailed );
-
- stackPtr->count += kStackListIncrement;
- }
-
- // we have place to put the information now
-
- if( GXGetShapeType( sh ) == gxPictureType )
- count = GXGetPicture( sh, nil, nil, nil, nil );
- else
- count = 1;
-
- HLock((Handle) stackPtr->stack); smptr = &( (* stackPtr->stack)[ stackPtr->mark ] );
-
- smptr->sh = sh;
- smptr->mark = 0;
- smptr->count = count;
-
- // the picture shapes do not get 'freed' and therefore the owner
- // count of style, ink, and transform are already set for this -- no need to clone them
-
- smptr->savestyle = stackPtr->savestyle;
- smptr->saveink = stackPtr->saveink;
- smptr->savetransform = stackPtr->savetransform;
-
- HUnlock((Handle) stackPtr->stack );
-
- stackPtr->savestyle = nil; // make sure we clean these for the next shape to use
- stackPtr->saveink = nil; // -- these objects get disposed at TMPopShape
- stackPtr->savetransform = nil;
-
- stackPtr->mark += 1; // bump the stack mark
-
- // we need to append the transform of this picture shape to the transform list in the stack
- // because of the way the stack manipulation scheme works the transform that we get from
- // the shape is always the correct one -- that is, the shapes on the stack always represent
- // the 'correct' the state
-
- status = TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( sh ) );
-
- // we are done
-
- GrowStackFailed:
-
- return( status );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMPopShape
-
- this routine removes the reference to the topmost entry in the stack
-
- -------------------------------------------------------------------------------*/
- void TMPopShape( TShapeStack *stackPtr )
- {
- TShapeNMark *smptr;
-
- short indx;
-
- gxTransform *trptr;
-
- check( 0 < stackPtr->mark );
-
- HLock((Handle) stackPtr->stack ); // lock this down so that we can call gx graphics
-
- smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] );
-
- if( smptr->savestyle )
- {
- GXSetShapeStyle( smptr->sh, smptr->savestyle );
- GXDisposeStyle( smptr->savestyle );
- }
-
- if( smptr->saveink )
- {
- GXSetShapeInk( smptr->sh, smptr->saveink );
- GXDisposeInk( smptr->saveink );
- }
-
- if( smptr->savetransform )
- {
- GXSetShapeTransform( smptr->sh, smptr->savetransform );
- GXDisposeTransform( smptr->savetransform );
- }
-
- HUnlock((Handle) stackPtr->stack );
-
- stackPtr->mark -= 1;
-
- if( ( kStackListIncrement * 2 ) < ( stackPtr->count - stackPtr->mark ) )
- {
- // the stack is too big and we need to shirk it
-
- SetHandleSize((Handle) stackPtr->stack, sizeof( TShapeNMark ) *
- ( stackPtr->count - kStackListIncrement ) );
-
- ncheck( MemError() ); // shrinking a handle should never result in an error
-
- stackPtr->count -= kStackListIncrement;
- }
-
- // because there is no good way to un-concatenate a transform we need to
- // rebuild the list to all the shapes - 1
-
- if( 0 < stackPtr->mark )
- {
- smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] ); // a pointer to the last shape
-
- // we only do this if the next shape is not the last in the picture
-
- if( smptr->mark < smptr->count )
- {
- if( 0 <= ( indx = ( stackPtr->tr.mark - stackPtr->tr.top ) - 1 ) ) // transforms on the stack
- {
- HLock((Handle) stackPtr->tr.list );
-
- trptr = & (* stackPtr->tr.list)[ stackPtr->tr.top ];
-
- for( ; indx >= 0; --indx )
- {
- GXDisposeTransform( *trptr++ );
- }
-
- HUnlock((Handle) stackPtr->tr.list );
- }
-
- // because this is the only place where we remove items of the transform stack
- // we check to see if it is suitable to be shrunk
-
- if( ( kStackListIncrement * 2 ) < ( stackPtr->tr.count - stackPtr->tr.mark ) )
- {
- SetHandleSize((Handle) stackPtr->tr.list, sizeof( gxTransform ) *
- ( stackPtr->tr.count - kStackListIncrement ) );
- ncheck( MemError() ); // ditto
-
- stackPtr->tr.count -= kStackListIncrement;
- }
-
- // at this point there are not transforms on the stack and tr.mark = tr.top
-
- stackPtr->tr.mark = stackPtr->tr.top; // we now restore the stack to the top
- stackPtr->tr.seed += 1; // make sure to invalidate the seed
-
- // now we push the transform of each of the shapes that remain on the regular stack
-
- indx = stackPtr->mark - 1; // the count of the shapes on the stack (0 based)
-
- if( 0 <= indx )
- {
- HLock((Handle) stackPtr->stack );
-
- smptr = & (* stackPtr->stack)[ 0 ];
-
- for( ; indx >= 0; --indx )
- {
- (void) TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( smptr->sh ) );
-
- smptr += 1; // advance the pointer
- }
-
- HUnlock((Handle) stackPtr->stack );
- }
- }
- }
- }
- /*-------------------------------------------------------------------------------
-
- TMRewindStack
-
- this routine resets the field in the stack so that it can be used again
- from the beginning. note that this routine does not clear the transforms
- that are located above the top of the transform stack
-
- -------------------------------------------------------------------------------*/
- void TMRewindStack( TShapeStack *stackPtr )
- {
- TShapeNMark *smptr;
-
- short count;
-
- check( 0 < stackPtr->mark ); // make sure that we have something to rewind in
-
- if( 1 < ( count = stackPtr->mark ) ) // this is how many shapes there are on the stack
- {
- short indx = count - 1;
-
- HLock((Handle) stackPtr->stack ); smptr = & (* stackPtr->stack)[ indx ];
-
- for( ; 1 <= indx ; --indx )
- {
-
- #if DEBUGLEVEL>0
-
- if( smptr->sh == nil ) Debugger( );
-
- GXValidateShape( smptr->sh );
-
- if( smptr->savestyle ) GXValidateStyle( smptr->savestyle );
- if( smptr->saveink ) GXValidateInk( smptr->saveink );
- if( smptr->savetransform ) GXValidateTransform( smptr->savetransform );
- #endif
-
- if( smptr->savestyle )
- {
- GXSetShapeStyle( smptr->sh, smptr->savestyle );
- GXDisposeStyle( smptr->savestyle );
- }
-
- if( smptr->saveink )
- {
- GXSetShapeInk( smptr->sh, smptr->saveink );
- GXDisposeInk( smptr->saveink );
- }
-
- if( smptr->savetransform )
- {
- GXSetShapeTransform( smptr->sh, smptr->savetransform );
- GXDisposeTransform( smptr->savetransform );
- }
-
- smptr -= 1;
- }
-
- // now we reset the mark on the topmost shape and the index in the stack
-
- HUnlock((Handle) stackPtr->stack );
-
- stackPtr->mark = 1; // leave the top shape on the stack
- }
-
- // now we deal with all of the transforms
-
-
- if( count = stackPtr->tr.mark - stackPtr->tr.top )
- {
- gxTransform *trptr;
-
- short indx = count - 1;
-
- HLock((Handle) stackPtr->tr.list );
-
- trptr = & (* stackPtr->tr.list)[ stackPtr->tr.top ];
-
- for( ; indx >= 0 ; --indx )
- {
- GXDisposeTransform( *trptr++ );
- }
-
- HUnlock((Handle) stackPtr->tr.list );
-
- stackPtr->tr.mark = stackPtr->tr.top;
- }
-
- // make sure that the mark on the stack points to the right shape
-
- smptr = & (* stackPtr->stack)[ 0 ];
- smptr->mark = 0;
-
- // and finally we restore the index for the shape and push the transform for it
-
- stackPtr->index = 0;
-
- (void) TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( smptr->sh ) );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMPeekShape
-
- this routine adds a shape and picture to the stack
-
- -------------------------------------------------------------------------------*/
- void TMPeekShape( gxShape *shptr, long *markptr, long *countptr, TShapeStack *stackPtr )
- {
- TShapeNMark *smptr;
-
- check( 0 < stackPtr->mark );
-
- smptr = &( (* stackPtr->stack)[ stackPtr->mark - 1 ] );
-
- if( shptr != nil ) *shptr = smptr->sh;
- if( markptr != nil ) *markptr = smptr->mark;
- if( countptr != nil ) *countptr = smptr->count;
- }
-
- /*-------------------------------------------------------------------------------
-
- TMGrabShape
-
- this shape returns the shape to which the stack points to currently
- setting the style and ink appropriately. the clients should call
- TMFreeShape after it is done processing the shape
-
- -------------------------------------------------------------------------------*/
- gxShape TMGrabShape( TShapeStack *stackPtr )
- {
- TShapeNMark *smptr;
-
- gxShape sh;
-
- check( 0 < stackPtr->mark );
-
- smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] );
-
- smptr->mark += 1;
-
- #ifndef print_backwards
- (void) GXGetPictureParts( smptr->sh, smptr->mark, 1, &stackPtr->sh,
- &stackPtr->newstyle, &stackPtr->newink, &stackPtr->newtransform );
- #else
- (void) GXGetPictureParts( smptr->sh, smptr->count - smptr->mark + 1, 1, &stackPtr->sh,
- &stackPtr->newstyle, &stackPtr->newink, &stackPtr->newtransform );
- #endif
- sh = stackPtr->sh;
-
- #if DEBUGLEVEL>0
- GXValidateShape( sh );
-
- if( stackPtr->newstyle ) GXValidateStyle( stackPtr->newstyle );
- if( stackPtr->newink ) GXValidateInk( stackPtr->newink );
- if( stackPtr->newtransform ) GXValidateTransform( stackPtr->newtransform );
- #endif
-
- GXIgnoreGraphicsNotice( style_already_set );
- GXIgnoreGraphicsNotice( ink_already_set );
- GXIgnoreGraphicsNotice( transform_already_set );
-
- // note: we need to clone the shapes attributes before we fold them into the shape because
- // everytime that SetShapeXXXX() is called it disposes of the shapes current attribute
- // and it sets it to be the new one.
-
- if( stackPtr->newstyle )
- {
- stackPtr->savestyle = GXCloneStyle( GXGetShapeStyle( sh ) );
- GXSetShapeStyle( sh, stackPtr->newstyle );
- }
-
- if( stackPtr->newink )
- {
- stackPtr->saveink = GXCloneInk( GXGetShapeInk( sh ) );
- GXSetShapeInk( sh, stackPtr->newink );
- }
-
- if( stackPtr->newtransform )
- {
- stackPtr->savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
- GXSetShapeTransform( sh, stackPtr->newtransform );
- }
- else
- {
- gxTransform xform;
-
- if( 1 >= GXGetTransformOwners( xform = GXGetShapeTransform( sh ) )
- && GXGetShapeType( sh ) == gxPictureType )
- {
- check( GXGetTransformOwners( xform ) == 1 );
-
- stackPtr->savetransform = GXCloneTransform( xform );
-
- xform = GXCopyToTransform( nil, xform );
- GXSetShapeTransform( sh, xform );
- GXDisposeTransform( xform );
- }
- }
-
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
-
- // this tells us what place we're at
-
- if( GXGetShapeType( sh ) != gxPictureType ) stackPtr->index += 1;
-
- return( sh );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMNextShape
-
- this routine returns the next available shape which is not a picture
-
- -------------------------------------------------------------------------------*/
- gxShape TMNextShape( TShapeStack *stackPtr )
- {
- OSErr status;
-
- gxShape sh = nil;
-
- for(;;)
- {
- long indx;
- long count;
-
- TMPeekShape( nil, &indx, &count, stackPtr );
-
- if( indx < count )
- {
- sh = TMGrabShape( stackPtr );
-
- if( GXGetShapeType( sh ) == gxPictureType )
- {
- nrequire( status = TMPushShape( stackPtr, sh ), PushShapeFailed );
- }
- else
- break;
- }
- else
- {
- TMPopShape( stackPtr );
- }
-
- if( emptystackq( stackPtr ) ) { sh = nil; break; }
- }
-
- return( sh );
-
- PushShapeFailed:
- return( nil );
- }
- /*-------------------------------------------------------------------------------
-
- TMSkipShape
-
- this routine advances the shape marker
-
- -------------------------------------------------------------------------------*/
- void TMSkipShape( TShapeStack *stackPtr )
- {
- if( TMNextShape( stackPtr ) )
- {
- TMFreeShape( stackPtr );
- }
- }
-
- /*-------------------------------------------------------------------------------
-
- TMFreeShape
-
- this routine undoes all the changes that TMGrabShape has to do in order
- to work
-
- -------------------------------------------------------------------------------*/
- void TMFreeShape( TShapeStack *stackPtr )
- {
- gxShape sh = stackPtr->sh;
-
- GXIgnoreGraphicsNotice( style_already_set );
- GXIgnoreGraphicsNotice( ink_already_set );
- GXIgnoreGraphicsNotice( transform_already_set );
-
- if( stackPtr->savestyle != nil )
- {
- GXSetShapeStyle( sh, stackPtr->savestyle );
- GXDisposeStyle( stackPtr->savestyle );
- stackPtr->savestyle = nil;
- }
-
- if( stackPtr->saveink != nil )
- {
- GXSetShapeInk( sh, stackPtr->saveink );
- GXDisposeInk( stackPtr->saveink );
- stackPtr->saveink = nil;
- }
-
- #ifdef print_transform_mapping
- {
- gxTransform xform;
- long map[ 9 ];
-
- GXGetTransformMapping( xform = GXGetShapeTransform( sh ) , (gxMapping *) & map[ 0 ] );
- dprintf( notrace, "after: 0x%8X\n[ %F %F %T ]\n[ %F %F %T ]\n[ %F %F %T ]",
- xform,
- map[ 0 ], map[ 1 ], map[ 2 ],
- map[ 3 ], map[ 4 ], map[ 5 ],
- map[ 6 ], map[ 7 ], map[ 8 ] );
- }
- #endif
-
- if( stackPtr->savetransform != nil )
- {
- GXSetShapeTransform( sh, stackPtr->savetransform );
- GXDisposeTransform( stackPtr->savetransform );
- stackPtr->savetransform = nil;
- }
-
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
-
- }
- /*-------------------------------------------------------------------------------
-
- TMFixOverrides
-
- this routine sets the overrides on a shape and saves the shapes normal
- attributes in a special data structure
-
- -------------------------------------------------------------------------------*/
- void TMFixOverrides( gxShape sh, gxStyle newstyle, gxInk newink, gxTransform newtransform,
- TTMShapeOverrides *overPtr )
- {
- overPtr->sh = sh;
-
- GXIgnoreGraphicsNotice( style_already_set );
- GXIgnoreGraphicsNotice( ink_already_set );
- GXIgnoreGraphicsNotice( transform_already_set );
-
- if( newstyle != nil )
- {
- overPtr->savestyle = GXCloneStyle( GXGetShapeStyle( sh ) );
- GXSetShapeStyle( sh, newstyle );
- }
-
- if( newink != nil )
- {
- overPtr->saveink = GXCloneInk( GXGetShapeInk( sh ) );
- GXSetShapeInk( sh, newink );
- }
-
- if( newtransform != nil )
- {
- overPtr->savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
- GXSetShapeTransform( sh, newtransform );
- }
-
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
-
- }
-
- /*-------------------------------------------------------------------------------
-
- TMRestoreOverrides
-
- this routine resets the shapes attributes (it undoes the work of the routine
- above).
-
- -------------------------------------------------------------------------------*/
-
- void TMRestoreOverrides( TTMShapeOverrides *overPtr )
- {
- gxShape sh = overPtr->sh;
-
- GXIgnoreGraphicsNotice( style_already_set );
- GXIgnoreGraphicsNotice( ink_already_set );
- GXIgnoreGraphicsNotice( transform_already_set );
-
- if( overPtr->savestyle != nil )
- {
- GXSetShapeStyle( sh, overPtr->savestyle );
- GXDisposeStyle( overPtr->savestyle );
- overPtr->savestyle = nil;
- }
-
- if( overPtr->saveink != nil )
- {
- GXSetShapeInk( sh, overPtr->saveink );
- GXDisposeInk( overPtr->saveink );
- overPtr->saveink = nil;
- }
-
- if( overPtr->savetransform != nil )
- {
- GXSetShapeTransform( sh, overPtr->savetransform );
- GXDisposeTransform( overPtr->savetransform );
- overPtr->savetransform = nil;
- }
-
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
- GXPopGraphicsNotice();
-
- }
-
-
- /*-------------------------------------------------------------------------------
-
- TMConcatenateTransform
-
- this routine takes a transform and it concatenates it the the list. this
- function assumes that the stack has been initialized and that there is room
- for at least one entry
-
- returns
- any error returned by SetHandleSize();
-
- -------------------------------------------------------------------------------*/
- OSErr TMConcatenateTransform( TTransformList *trptr, gxTransform tr )
- {
- OSErr status = noErr;
-
- gxShapeType shType;
- gxMapping newtmap;
- long tagcount;
-
- check( trptr->top <= trptr->mark );
-
- shType = GetTransformClipType( tr );
- tagcount = GXGetTransformTags( tr, 'post', 1, gxSelectToEnd, nil );
-
- GXGetTransformMapping( tr, &newtmap );
-
- trptr->seed += 1; // bump the seed value so that we don't attach to this list
-
- // first we check to see if this is the first transform that we are adding to this list
-
- if( tagcount == 0 && TMTestIdentityMapping( &newtmap ) && shType == gxFullType )
- {
- trptr->seed -= 1; // this transform is not worthy!
- }
- else
- {
- if( trptr->top == trptr->mark ) goto PushTransform;
-
- // if we are here then we know we have at least one more transform on the stack
-
- if( tagcount == 0 && trptr->cliptype == gxFullType )
- {
- gxTransform toptr;
- gxTransform newtr;
-
- gxMapping curtmap;
-
- newtr = GXNewTransform();
- toptr = (* trptr->list)[ trptr->mark - 1 ];
-
- GXGetTransformMapping( toptr, &curtmap );
- MapMapping( &newtmap, &curtmap );
-
- GXSetTransformMapping( newtr, &newtmap );
- if( shType != gxFullType )
- {
- gxShape sh = GXGetTransformClip( tr );
-
- GXSetTransformClip( newtr, sh );
- trptr->cliptype = shType;
-
- GXDisposeShape( sh );
- }
-
- (* trptr->list)[ trptr->mark - 1 ] = newtr;
- GXDisposeTransform( toptr );
- }
- else
- {
- PushTransform:
- // we must push the new transform on the stack --
- // we first make sure that the stack can hold it
-
- if( trptr->count <= trptr->mark )
- {
- // we need to grow the handle
-
- SetHandleSize((Handle) trptr->list, sizeof( gxTransform ) *
- ( trptr->count + kStackListIncrement ) );
- nrequire( status = MemError(), GrowHandleFailed );
-
- trptr->count += kStackListIncrement;
- }
-
- // by this point we are assured that we have enough room to push the transform
-
- if( tagcount )
- (* trptr->list)[ trptr->mark ] = GXCloneTransform( tr );
- else
- (* trptr->list)[ trptr->mark ] = GXCopyToTransform( nil, tr );
-
- // and we increment the mark to show that we have a new transform
-
- trptr->mark += 1;
-
- if( tagcount == 0 )
- trptr->cliptype = shType;
- else
- trptr->cliptype = gxEmptyType; // prevent further concatenation
- }
- }
-
- GrowHandleFailed:
-
- return( status );
- }
- /*-------------------------------------------------------------------------------
-
- TMInsertTMClip
-
- this routine inserts a transform at the top of the transform list.
-
- -------------------------------------------------------------------------------*/
- OSErr TMInsertTMClip( TTransformList *trptr, gxTransform tr )
- {
- OSErr status = noErr;
-
- gxTransform *aptr;
- gxTransform *bptr;
-
- short indx;
-
- check( trptr->top <= trptr->mark );
-
- // first we check to see if we have enough room to add the transform
-
- if( trptr->count <= trptr->mark )
- {
- // we need to grow the handle
-
- SetHandleSize((Handle) trptr->list, sizeof( gxTransform ) *
- ( trptr->count + kStackListIncrement ) );
- nrequire( status = MemError(), GrowStackFailed );
-
- trptr->count += kStackListIncrement;
- }
-
- // to insert the transform we need to need to move down all of the other ones
-
- indx = trptr->mark - 1; // make the count zero based
-
- aptr = & (* trptr->list)[ indx ]; // the last transform on the list
- bptr = aptr + 1;
-
- indx -= trptr->top; // only move the transforms above the top of the stack
-
- for( ; indx >= 0; --indx )
- {
- *bptr = *aptr;
-
- aptr -= 1;
- bptr -= 1;
- }
-
- (* trptr->list)[ trptr->top ] = tr; // this is the transform that we had to insert
-
- trptr->top += 1;
- trptr->mark += 1;
- trptr->seed += 1;
-
- GrowStackFailed:
- return( status );
- }
- /*-------------------------------------------------------------------------------
-
- TMRemoveTMClip
-
- this routine undoes the changes made by the one previously. that is, it
- removes the transform from the top of the transform list.
-
- -------------------------------------------------------------------------------*/
- void TMRemoveTMClip( TTransformList *trptr )
- {
- gxTransform *aptr;
- gxTransform *bptr;
-
- short indx;
-
- #if DEBUGLEVEL>0
-
- if( trptr->top <= 0 )
- DebugStr( "\ptrptr->top is bad" );
-
- #endif
-
- GXDisposeTransform( (* trptr->list)[ trptr->top - 1 ] );
-
- aptr = & (* trptr->list)[ trptr->top - 1 ];
- bptr = aptr + 1;
-
- indx = trptr->mark - trptr->top;
-
- for( ; indx >= 0; --indx )
- {
- *aptr++ = *bptr++;
- }
-
- trptr->top -= 1;
- trptr->mark -= 1;
- }
- /*-------------------------------------------------------------------------------
-
- TMResolveShape
-
- given a parameter block as described below this routine process the next
- shape from the stack and returns it to the client so it can futz with it.
-
- -------------------------------------------------------------------------------*/
- OSErr TMResolveShape( TResolveParam *rpptr, Boolean doresolve )
- {
- OSErr status = noErr;
-
- TRNABlock rna;
-
- gxShape sh;
- gxInk shink;
- gxColor shcolor;
-
- gxShapeType shType;
- gxInk tmink;
-
- // the first thing that we do is grab the next available shape from the stack
-
- sh = TMNextShape( &( rpptr->stack ) );
-
- // before we add the new shape to the list we make sure that the strand is initialized
-
- rna.root = nil; // initialize the picture strand
- rna.branch = nil;
- rna.node = nil;
- rna.seed = 0; // initialize the transform list seed
-
- rna.rootst = nil;
- rna.roottm = nil;
- rna.roottr = nil;
-
- if( sh != nil )
- {
- short iscopymode;
-
- shType = GXGetShapeType( sh );
-
- // now that we have a shape we need to figure out what the color that this shape will have
- // is if it where to render alone on a 'blank' frame buffer. to do this we start by setting
- // the variable shcolor to white [ /gray 1.0 ] and then combining the color contained
- // in the ink to using the transfer mode that the ink contains. once we have the
- // correct color we make a new ink and set the color of that ink to be the result of
- // the combination.
-
- // now we get the bounds of the shape -- we always do this transfer modes or not
-
- TMGetShapeBounds( &( rpptr->shbbox ), sh, &( rpptr->stack ), &( rpptr->bp ) );
-
- // and we check to see if we have a transfer mode
-
- shink = GXGetShapeInk( sh );
-
- if( doresolve )
- iscopymode = TMTestCopyMode( shink );
- else
- iscopymode = true; // treat all shapes as if they had copy mode
-
- if( shType == gxBitmapType )
- {
- gxShape sh2;
- gxBitmap thebits;
-
- // we have a bitmap shape -- oh God! -- what to do. when we have a bitmap it
- // draws on top of all of the shapes that it overlaps. to reproduce this effect
- // we need to create an offscreen and draw all of the previous shapes into it
- // and then draw the bitmap itself -- we ignore any transfer mode information
- // while rendering all of the shapes into the bitmap as these will be resolved
- // naturaly.
-
- if( ! iscopymode )
- {
- // one last chance to be in copy mode is if the bitmap is in or mode
-
- (void) GXGetBitmap( sh, &thebits, nil );
- if( thebits.pixelSize == 1 )
- {
- if( ( iscopymode = TMTestOrMode( shink ) ) ||
- ( iscopymode = TMTestMinMode( shink ) ) )
- {
- // we have to set a clip on this shape which corresponds to
- // bits that the user wants to or on the screen
-
- sh2 = TMResolveOrModeBitmap( sh );
- TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
-
- goto relaseClone;
- }
- }
- else
- {
- // check to see if the shape is transparent anyway
-
- if( ! (iscopymode = TMTestOrMode( shink ) ) ) iscopymode = TMTestMinMode( shink );
- }
- }
-
- if( ! iscopymode ) // if the bitmap is blitted with a transfer mode
- {
- if( rpptr->stack.index == 1 ) // if this is the first shape then this is all
- {
- sh2 = TMCombineBitmapColors( sh, shink, nil, nil, nil );
- TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
- }
- else
- {
- // we make a shape where all of the shapes are re-rendered into the bitmap
-
- sh2 = TMResolveBitmap( & rpptr->stack, nil, &( rpptr->shbbox ) );
- TMAttachShapeSimple( &rna, sh2, & rpptr->stack );
-
- // make sure that we don't re-do this below
- iscopymode = true;
- }
- }
- else
- {
- sh2 = GXCloneShape( sh );
- TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
- }
- relaseClone:
- GXDisposeShape( sh2 ); // balance the oc
-
- // check to see if we are done or if we need too
- }
- else
- {
- // if we have a single colored shape and the transfer mode on it is orMode
- // (in gx graphics implemented as a flavor of the copy code) then we don't need to
- // resolve it but we still need to change the
-
- // if we still have a transfer mode then we have to do something drastic
-
- if( iscopymode == false )
- {
- TMCombineColors( &shcolor, shink, nil );
- GXSetInkColor( tmink = GXNewInk(), &shcolor );
-
- if( ! iscopymode ) iscopymode = TMTestOrMode( shink );
- }
- else
- {
- // we don't have a transfer mode and we need to give this shape the
- // overriding ink that i had originally when we pulled it out of the picture
-
- if( rpptr->stack.newink )
- tmink = GXCloneInk( shink );
- else
- tmink = nil; // leave the shape with it's original ink
- }
-
- // by this point the 'correct' color for this shape is contained in shcolor and an ink
- // in the variable tmink. the next step is to start a picture for this shape. this is
- // accomplished by means of the rna structure. for those familiar with the biological
- // processes at the molecular level (MIT 7.01) rna is the molecular entity that is
- // responsible for building up proteins in the cells citoplasm. this action is acomplished
- // by transcribing a series of aminoacid sequences one atom at the time. similarly the
- // rna data structure serves to build up the picture of the 'resolved' shape one shape
- // at the time. every time that we have a new shape that we need to add to the
- // picture 'strand' we call TMAttachShape() and pass it to it. to begin we set the
- // rna.root shape to be nil and at the end we can extract out finished shape from
- // rna.root using the rna.rootm and rna.roottr as the overriding ink and transforms for it.
-
- TMAttachShape( &rna, sh, tmink, &( rpptr->stack ) ); // and attach the shape
- if( tmink ) GXDisposeInk( tmink ); // we no longer own this
- }
-
- // check to see if we have a transfer mode
-
- if( ( iscopymode == false ) && ( 1 < rpptr->stack.index ) )
- {
- TTModeStack stack; // this is the transfer mode stack
- gxRectangle shbbox;
-
- // if we are inside this loop this means that we have a transfer mode to resolve.
- // we make a new stack in which we can keep the transfer mode information.
-
- nrequire( status = TMNewTModeStack( &stack ), MakeTMStackFailed );
- nrequire( status = TMPushTMBlock( &stack, sh, &( rpptr->shbbox ),
- &( rpptr->stack ) ),
- FirstPushBlockFailed );
-
- TMFreeShape( &( rpptr->stack ) ); // we release the shape
- TMRewindStack( &( rpptr->stack ) ); // and rewind the stack
-
- // this is where all the work goes on
-
- for(;;)
- {
- long indx;
- long count;
-
- gxRectangle sh2bbox;
-
- gxShape sh2;
- gxInk sh2ink;
- gxColor sh2color;
-
- gxInk tm2ink;
-
- sh2 = TMNextShape( &( rpptr->stack ) );
-
- TMPeekTMBlock( &indx, &count, &shbbox, &stack );
-
- if( indx < count )
- {
- TMBumpTMBlock( &stack, &rpptr->stack ); // this bumps the mark in the field
- TMGetShapeBounds( &sh2bbox, sh2, &( rpptr->stack ), &( rpptr->bp ) );
-
- // see if these two shapes intersect
-
- if( GXIntersectRectangle( &sh2bbox, &sh2bbox, &shbbox )
- && ( ! emptyrectangle( &sh2bbox ) ) )
- {
- gxShapeType sh2Type = GXGetShapeType( sh2 );
-
- // we have a shape that intersects -- ho ho ho
-
- iscopymode = TMTestCopyMode( sh2ink = GXGetShapeInk( sh2 ) );
-
- // we need to run this shape through all of the inks in the stack
-
- if( sh2Type != gxBitmapType )
- {
- TMCombineColors( &sh2color, sh2ink, &stack );
- GXSetInkColor( tm2ink = GXNewInk(), &sh2color );
- TMAttachShape( &rna, sh2, tm2ink, &( rpptr->stack ) );
-
- GXDisposeInk( tm2ink ); // we are done with this
-
- // see if the shape has a transfer mode of its own
-
- if( ( 1 < indx ) && ( iscopymode == false ) )
- {
- nrequire( status = TMPushTMBlock( &stack, sh2, &sh2bbox,
- &( rpptr->stack ) ), PushBlockFailed );
-
- TMFreeShape( &( rpptr->stack ) );
- TMRewindStack( &( rpptr->stack ) );
- }
- else
- {
- TMFreeShape( &( rpptr->stack ) );
- }
- }
- else
- {
- if( iscopymode != false )
- {
- sh2 = TMCombineBitmapColors( sh2, sh2ink, &stack, &sh2bbox, &( rpptr->stack.tr ) );
- TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
- }
- else
- {
- sh2 = TMResolveBitmap( &rpptr->stack, &stack, &sh2bbox );
- TMAttachShapeSimple( &rna, sh2, &rpptr->stack );
- }
-
- GXDisposeShape( sh2 );
- TMFreeShape( &( rpptr->stack ) );
- }
- }
- else
- {
- TMFreeShape( &( rpptr->stack ) );
- }
- }
- else
- {
- TMPopTMBlock( &stack, &( rpptr->stack ) );
-
- // we should not release the shape that we have when we terminate
- // because the client will take care of that.
-
- if( ! emptystackq( &stack ) )
- TMFreeShape( &( rpptr->stack ) );
- else
- break;
- }
- }
-
- FirstPushBlockFailed:
- PushBlockFailed:
-
- check( rpptr->stack.tr.top == 0 );
-
- TMDisposeTModeStack( &stack );
-
- }
- }
-
- // at this point we are all done. our product is the root of the rna strand.
- // also, since we took either one of the two paths we have now returned the
- // shape to the 'grabbed' state. the shape is freed at the release shape call
-
- rpptr->sh = ( rna.root == nil ) ? rna.node : rna.root;
- rpptr->st = rna.rootst;
- rpptr->tm = rna.roottm;
- rpptr->tr = rna.roottr;
-
- MakeTMStackFailed:
- PushShapeFailed:
- return( status );
- }
- /*-------------------------------------------------------------------------------
-
- TMReleaseShape
-
- this call lets the resolver know that the client is done with this shape.
-
- -------------------------------------------------------------------------------*/
- void TMReleaseShape( TResolveParam *rpptr )
- {
- check( rpptr->sh );
-
- GXDisposeShape( rpptr->sh ); // balance the owner count of everyting
-
- if( rpptr->st != nil ) GXDisposeStyle( rpptr->st );
- if( rpptr->tm != nil ) GXDisposeInk( rpptr->tm );
- if( rpptr->tr != nil ) GXDisposeTransform( rpptr->tr );
-
- TMFreeShape( &( rpptr->stack ) );
- }
- /*-------------------------------------------------------------------------------
-
- TMAttachShape
-
- this call attaches a shape to an RNA strand
-
- -------------------------------------------------------------------------------*/
- void TMAttachShape( TRNABlock *rnaptr, gxShape sh, gxInk tm, TShapeStack *stackPtr )
- {
- gxStyle shstyle;
- gxInk shink;
- gxTransform shtransform;
-
- short indx;
- gxTransform *trptr;
-
- short clipflag = false;
-
- // set the shapes up
-
- if( sh == stackPtr->sh )
- {
- shstyle = stackPtr->newstyle;
- shtransform = stackPtr->newtransform;
- if( tm ) shink = tm; else shink = stackPtr->newink;
- }
- else
- {
- shstyle = nil;
- shink = tm;
- shtransform = nil;
- }
-
- sh = GXCloneShape( sh );
-
- if( shstyle != nil ) GXCloneStyle( shstyle );
- if( shink != nil ) GXCloneInk( shink );
- if( shtransform != nil ) GXCloneTransform( shtransform );
-
- // check to see if the seed that we have is the same as the one in the
- // stack pointer tr list. if they are then we add to the node and not to the root
- // note: a rnaptr->seed of 0 means that it is unitialized as stackPtr->tr.seed cannot == 0
-
- if( ( rnaptr->seed != stackPtr->tr.seed ) || ( rnaptr->branch == nil ) )
- {
- indx = stackPtr->tr.mark - 1; // this is the index for the top transform on the stack
- trptr = & (* stackPtr->tr.list)[ indx ];
-
- if( 0 <= indx ) // if there are more transforms still we DO need a picture
- {
- gxShape sh2;
-
- sh2 = GXNewPicture( 1, &sh, &shstyle, &shink, &shtransform );
-
- GXDisposeShape( sh );
-
- if( shstyle != nil ) { GXDisposeStyle( shstyle ); shstyle = nil; }
- if( shink != nil ) { GXDisposeInk( shink ); shink = nil; }
- if( shtransform != nil ) { GXDisposeTransform( shtransform ); shtransform = nil; }
-
- // this picture now can become the node to which other shapes can be added to
- // as long and the seed value in rna and stackPtr->tr remains the same
-
- rnaptr->branch = sh2;
-
- sh = sh2;
-
- GXSetShapeTransform( sh, *trptr );
-
- indx -= 1;
- trptr -= 1;
- }
-
- for( ; indx >= 0 ; --indx )
- {
- gxShape sh2;
-
- sh2 = GXNewPicture( 1, &sh, nil, nil, nil );
-
- GXDisposeShape( sh );
-
- sh = sh2;
-
- GXSetShapeTransform( sh, *trptr );
-
- trptr -= 1;
- }
-
- // here we have a shape suitable for being appended to the list
-
- if( ( rnaptr->root == nil ) && ( rnaptr->node == nil ) )
- {
- rnaptr->node = GXCloneShape( sh );
-
- if( shstyle != nil ) GXCloneStyle( shstyle ); rnaptr->rootst = shstyle;
- if( shink != nil ) GXCloneInk( shink ); rnaptr->roottm = shink;
- if( shtransform != nil ) GXCloneTransform( shtransform ); rnaptr->roottr = shtransform;
- }
- else
- {
- if( rnaptr->root == nil )
- {
- rnaptr->root = GXNewPicture( 1, &rnaptr->node, &rnaptr->rootst,
- &rnaptr->roottm, &rnaptr->roottr );
- GXDisposeShape( rnaptr->node );
-
- // the only time that we want to replace the brach here is if there is
- // no root and no branch. if there is a node but no root the branch, if
- // set, is correct. if the branch is not set then it is the same as
- // the root because the node is not a picture
-
- if( rnaptr->branch == nil )
- rnaptr->branch = rnaptr->root;
-
- if( rnaptr->rootst != nil ) { GXDisposeStyle( rnaptr->rootst ); rnaptr->rootst = nil; }
- if( rnaptr->roottm != nil ) { GXDisposeInk( rnaptr->roottm ); rnaptr->roottm = nil; }
- if( rnaptr->roottr != nil ) { GXDisposeTransform( rnaptr->roottr ); rnaptr->roottr = nil; }
- }
-
- GXSetPictureParts( rnaptr->root, 0, 0, 1, &sh, &shstyle, &shink, &shtransform );
- }
- }
- else
- {
- check( rnaptr->branch != nil );
-
- // the seed values are equal so we add the shape to the branch instead
-
- GXSetPictureParts( rnaptr->branch, 0, 0, 1, &sh, &shstyle, &shink, &shtransform );
- }
-
- GXDisposeShape( sh );
-
- if( shstyle != nil ) GXDisposeStyle( shstyle );
- if( shink != nil ) GXDisposeInk( shink );
- if( shtransform != nil ) GXDisposeTransform( shtransform );
-
- rnaptr->seed = stackPtr->tr.seed;
-
- }
-
- /*-------------------------------------------------------------------------------
-
- TMAttachShapeSimple
-
- this routine attaches a shape to a strand so that it is at the top most
- level. it also nukes the transform seed preventing any more shapes from
- being added to the branch of the block.
-
- -------------------------------------------------------------------------------*/
-
- void TMAttachShapeSimple( TRNABlock *rnaptr, gxShape sh, TShapeStack *stackPtr )
- {
- TTransformList *listPtr = &stackPtr->tr;
-
- // first we need to concatenate this with all of the clips that are on the stack
-
- if( 0 < listPtr->top )
- {
- short indx;
- gxTransform *trptr;
-
- // this means that we have clips that we need to attach to this shape
-
- HLock((Handle) listPtr->list );
-
- trptr = & (* listPtr->list)[ listPtr->top -1 ];
-
- GXSetShapeTransform( sh, *trptr-- );
-
- indx = listPtr->top - 2; // -1 for zero base and -1 for the one we did already
-
- if( 0 < indx )
- {
-
- for( ; indx >= 0; --indx )
- {
- sh = GXNewPicture( 1, &sh, nil, nil, nil );
-
- GXSetShapeTransform( sh, *trptr-- );
- }
- }
-
- HUnlock((Handle) listPtr->list );
- }
-
- // check to see if the root node is not nil
-
- if( ( rnaptr->node == nil ) && ( rnaptr->root == nil ) )
- {
- // this is the first shape on the strand
-
- rnaptr->root = GXNewPicture( 1, &sh, nil, nil, nil );
-
- rnaptr->rootst = nil;
- rnaptr->roottm = nil;
- rnaptr->roottr = nil;
- }
- else
- {
- if( rnaptr->root == nil )
- {
- rnaptr->root = GXNewPicture( 1, &rnaptr->node, &rnaptr->rootst,
- &rnaptr->roottm, &rnaptr->roottr );
- GXDisposeShape( rnaptr->node );
-
- if( rnaptr->rootst != nil ) { GXDisposeStyle( rnaptr->rootst ); rnaptr->rootst = nil; }
- if( rnaptr->roottm != nil ) { GXDisposeInk( rnaptr->roottm ); rnaptr->roottm = nil; }
- if( rnaptr->roottr != nil ) { GXDisposeTransform( rnaptr->roottr ); rnaptr->roottr = nil; }
- }
-
- GXSetPictureParts( rnaptr->root, 0, 0, 1, &sh, nil, nil, nil );
- }
-
- rnaptr->seed = 0; // make sure that all further shapes are added to the root
- }
-
- /*-------------------------------------------------------------------------------
-
- TMTestOrMode
-
- this call checks to see if the transfer mode for an ink is something other
- than copy. it also check and fixes up any transfer mode that is xor and
- pixel xor.
-
- -------------------------------------------------------------------------------*/
- Boolean TMTestOrMode( gxInk shink )
- {
- gxTransferMode shmode;
-
- Boolean result;
-
- short count;
-
- result = true; // assume that the transfer mode is or
-
- GXGetInkTransfer( shink, &shmode );
-
- if( count = TMGetSpaceComponentCount( shmode.space ) )
- {
- gxTransferComponent *trc = shmode.component;
-
- do
- {
- // there are two possible representations of or mode
- // one is gxCopy mode where ->sourceMinimum == ->sourceMaximum
- // and the other is
- // gxMinimum and ->sourceMinimum == 0 and ->sourceMaximum == 0xFFFF
-
- if( ( trc->mode == gxCopyMode &&
- trc->sourceMinimum == trc->sourceMaximum ) )
- {
- // do nothing; we have what we want
- }
- else
- {
- result = false;
- break;
- }
-
- trc += 1;
-
- } while( 0 < --count );
- }
-
- return( result );
-
- }
-
- /*-------------------------------------------------------------------------------
-
- TMTestCopyMode
-
- this call checks to see if the transfer mode for an ink is something other
- than copy. it also check and fixes up any transfer mode that is xor and
- pixel xor.
-
- -------------------------------------------------------------------------------*/
- Boolean TMTestCopyMode( gxInk shink )
- {
- gxTransferMode shmode;
-
- Boolean result;
-
- short indx;
- short count;
-
- gxTransferComponent *trComponent;
-
- GXGetInkTransfer( shink, &shmode );
-
- count = TMGetSpaceComponentCount( shmode.space );
-
- // if we are replicating the same component the only check the first one
-
- if( count && ( shmode.flags & gxSingleComponentTransfer ) ) count = 1;
-
- result = true; // assume that the transfer mode is copy
-
- trComponent = shmode.component;
- for( indx = 0; indx < count; ++indx )
- {
-
- if ( (trComponent->mode != gxCopyMode) ||
- (trComponent->sourceMinimum != 0x0000) ||
- (trComponent->sourceMaximum != 0xFFFF) ||
- (trComponent->deviceMinimum != 0x0000) ||
- (trComponent->deviceMaximum != 0xFFFF) ||
- (trComponent->clampMinimum != 0x0000) ||
- (trComponent->clampMaximum != 0xFFFF)
- )
- {
- result = false;
- break;
- }
-
- ++trComponent;
- }
-
- return( result );
-
- }
- /*-------------------------------------------------------------------------------
-
- TMTestComponentMode
-
- this call checks to see if the component for a transfer mode is the given one.
-
- -------------------------------------------------------------------------------*/
-
- Boolean TMTestComponentMode( gxTransferComponent *component, unsigned char mode )
- {
- if( ( component->mode == mode ) &&
- ( component->deviceMinimum == 0 ) &&
- ( component->clampMinimum == 0 ) &&
- ( component->deviceMaximum == 0xFFFF ) &&
- ( component->clampMaximum == 0xFFFF ) )
- return( true );
- else
- return( false );
- }
-
- /*----------------------------------------------------------------------------------
-
- TMGetSpaceComponentCount
-
- this routine returns the number of components for a color space.
-
- ----------------------------------------------------------------------------------*/
- short TMGetSpaceComponentCount( gxColorSpace space )
- {
- short count;
-
- switch( space )
- {
- case gxRGBSpace:
- case gxHSVSpace:
- case gxHLSSpace:
- case gxYXYSpace:
- case gxXYZSpace:
- case gxLUVSpace:
- case gxLABSpace:
- case gxYIQSpace:
- case gxRGB16Space:
- case gxRGB32Space:
- case gxHSV32Space:
- case gxHLS32Space:
- case gxYXY32Space:
- case gxXYZ32Space:
- case gxLUV32Space:
- case gxLAB32Space:
- case gxYIQ32Space:
- count = 3;
- break;
-
- case gxRGBASpace:
- case gxCMYKSpace:
- case gxARGB32Space:
- case gxCMYK32Space:
- count = 4;
- break;
-
-
- case gxGraySpace:
- case gxIndexedSpace:
- count = 1;
- break;
-
- case gxGrayASpace:
- count = 2;
- break;
-
- default:
- count = 0;
- break;
-
- }
-
- return( count );
- }
- /*----------------------------------------------------------------------------------
-
- TMNewTModeStack
-
- this routine returns the number of components for a color space.
-
- ----------------------------------------------------------------------------------*/
-
- OSErr TMNewTModeStack( TTModeStack *stackPtr )
- {
- OSErr status;
-
- stackPtr->stack = (TTModeBlock **) NewHandle( kStackListIncrement * sizeof( TTModeBlock ) );
- nrequire( status = MemError(), MakeStackFailed );
-
- stackPtr->mark = 0;
- stackPtr->count = kStackListIncrement;
-
- MakeStackFailed:
- return( status );
- }
-
- /*----------------------------------------------------------------------------------
-
- TMDisposeTModeStack
-
- this routine gets rid of a TMode stack.
-
- ----------------------------------------------------------------------------------*/
- void TMDisposeTModeStack( TTModeStack *stackPtr )
- {
- check( stackPtr->mark == 0 );
-
- DisposeHandle((Handle) stackPtr->stack );
- ncheck( MemError() );
-
- stackPtr->count = 0;
- }
- /*----------------------------------------------------------------------------------
-
- TMPushTMBlock
-
- this routine concatenates the information needed to render concatenated
- transfer modes.
-
- ----------------------------------------------------------------------------------*/
- OSErr TMPushTMBlock( TTModeStack *stackPtr,
- gxShape sh,
- gxRectangle *shbboxptr,
- TShapeStack *shstackPtr )
- {
- OSErr status;
-
- gxShape clipshape;
-
- gxTransform xform;
- gxMapping newmap;
-
- TTModeBlock *blockPtr;
-
- #if DEBUGLEVEL>0
-
- if( shstackPtr->index <= 1 )
- DebugStr( "\pthere are no shapes to push in TMPushTMBlock" );
-
- if( shstackPtr->tr.mark < shstackPtr->tr.top )
- DebugStr( "\pTM stack overflow in TMPushTMBlock" );
-
- #endif
-
- // now we make a new transform and assign to it the mapped shape
-
- xform = GXNewTransform();
-
- // the code below figures out the new clip for the shape that is being pushed on the stack.
-
- {
- gxShape otherclip = GXGetShapeClip( sh );
-
- gxShapeType shType = GXGetShapeType( sh );
-
- if( ( shType == gxTextType ) || ( shType == gxGlyphType ) || ( shType == gxLayoutType ) )
- {
-
- #if !defined( GraphicsLab ) && !defined( GraphicsScript)
- nrequire( status = TextToUnhintedPath( clipshape = GXCopyToShape( nil, sh ) ), TextToPathFailed);
- #else
- GXSetShapeType( clipshape = GXCopyToShape( nil, sh ), gxPathType );
- #endif
-
- }
- else
- {
- GXPrimitiveShape( clipshape = GXCopyToShape( nil, sh ) );
- }
-
- // ## bug number #1202310 -- transfer modes and lighting draw
- // sometimes shapes have the gxMapTransform attribute set. this causes the later
- // invocation of the MapShape call to do nothing and gives us the wrong clip
-
- GXSetShapeAttributes( clipshape, GXGetShapeAttributes( clipshape ) & ~gxMapTransformShape );
-
- // concatenate the clip we calculated with the shapes clip
-
- GXIntersectShape( clipshape, otherclip );
-
- // get the concatenated mapping which will take us to device space and map the clip
-
- if( TMGetDeviceMapping( &newmap, sh, & shstackPtr->tr ) )
- {
- GXMapShape( clipshape, &newmap );
- }
-
- GXDisposeShape( otherclip );
- }
-
- GXSetTransformClip( xform, clipshape );
- GXDisposeShape( clipshape );
-
- check( GXGetTransformOwners( xform ) == 1 );
-
- nrequire( status = TMInsertTMClip( &( shstackPtr->tr), xform ), InsertClipFailed );
-
- // now we do the ink -- first we make sure that we have enough room to put in a new block
-
- if( stackPtr->count <= stackPtr->mark )
- {
- // we need to grow the stack
-
- SetHandleSize((Handle) stackPtr->stack, sizeof( TTModeBlock ) *
- ( stackPtr->count + kStackListIncrement ) );
- nrequire( status = MemError(), GrowStackFailed );
-
- stackPtr->count += kStackListIncrement;
- }
-
- blockPtr = & (* stackPtr->stack)[ stackPtr->mark ]; // the next available space
-
- check( 1 < shstackPtr->index );
-
- blockPtr->mark = 1; // this is the index of the shape that we start at
- blockPtr->count = shstackPtr->index; // this is the index of ths shape that we are
-
- check( blockPtr->mark < blockPtr->count );
-
- blockPtr->tm = GXCloneInk( GXGetShapeInk( sh ) );
- blockPtr->shbbox = *shbboxptr;
- blockPtr->sh = GXCloneShape( sh );
-
- // we now bump the mark
-
- stackPtr->mark += 1;
-
- TextToPathFailed:
- GrowStackFailed:
- InsertClipFailed:
-
- return( status );
- }
- /*----------------------------------------------------------------------------------
-
- TMPopTMBlock
-
- this routine pops the topmost block from the transfer mode list.
-
- ----------------------------------------------------------------------------------*/
- void TMPopTMBlock( TTModeStack *stackPtr, TShapeStack *shstackPtr )
- {
- TTModeBlock *blockPtr;
-
- check( 0 < stackPtr->mark );
-
- #if DEBUGLEVEL>0
-
- if( stackPtr->mark <= 0 )
- DebugStr( "\pstackPtr->mark<=0" );
-
- #endif
-
- stackPtr->mark -= 1; // stack[ mark ] is now the last ink
-
- blockPtr = & (* stackPtr->stack)[ stackPtr->mark ]; // make room for the new ink
-
- GXDisposeInk( blockPtr->tm );
- GXDisposeShape( blockPtr->sh );
-
- // check to see if we need to shrink the stack
-
- if( ( 2 * kStackListIncrement ) < ( stackPtr->count - stackPtr->mark ) )
- {
- SetHandleSize((Handle) stackPtr->stack, sizeof( TTModeBlock ) *
- ( stackPtr->count - kStackListIncrement ) );
- ncheck( MemError() );
-
- stackPtr->count -= kStackListIncrement;
- }
-
- // now remove the clip from the transform stack
-
- TMRemoveTMClip( &( shstackPtr->tr ) );
- }
- /*----------------------------------------------------------------------------------
-
- TMPeekTMBlock
-
- this routine pops the topmost block from the transfer mode list.
-
- ----------------------------------------------------------------------------------*/
- void TMPeekTMBlock( long *indxptr, long *countptr, gxRectangle *shbboxptr, TTModeStack *stackPtr )
- {
- TTModeBlock *blockPtr;
-
- check( 0 < stackPtr->mark );
-
- blockPtr = & (* stackPtr->stack)[ stackPtr->mark - 1 ];
-
- if( indxptr != nil )
- *indxptr = blockPtr->mark;
-
- if( countptr != nil )
- *countptr = blockPtr->count;
-
- if( shbboxptr != nil )
- *shbboxptr = blockPtr->shbbox;
-
- }
- /*----------------------------------------------------------------------------------
-
- TMBumpTMBlock
-
- this routine increments the mark for a block. should maybe make it a macro.
-
- ----------------------------------------------------------------------------------*/
- void TMBumpTMBlock( TTModeStack *stackPtr, TShapeStack *shstackPtr )
- {
- TTModeBlock *blockPtr;
-
- blockPtr = & (* stackPtr->stack)[ stackPtr->mark - 1 ];
-
- blockPtr->mark = shstackPtr->index + 1;
- }
- /*----------------------------------------------------------------------------------
-
- TMCombineColors
-
- this routine calculates what the color should be by combining the inks in the
- ink blocks.
-
- ----------------------------------------------------------------------------------*/
- void TMCombineColors( gxColor *shcolorptr, gxInk shink, TTModeStack *stackPtr )
- {
- TTModeBlock *blockPtr;
- short indx;
-
- GXCombineColor( TMMakeWhite( shcolorptr ), shink ); // we start with white
-
- if( stackPtr != nil )
- {
- check( 0 < stackPtr->mark );
-
- indx = stackPtr->mark - 1; // these are the number of inks in the stack
-
- check( 0 <= indx );
-
- HLock((Handle) stackPtr->stack );
-
- blockPtr = & (* stackPtr->stack)[ indx ];
-
- for( ; indx >= 0; --indx )
- {
- GXCombineColor( shcolorptr, blockPtr->tm );
-
- blockPtr -= 1;
- }
-
- HUnlock((Handle) stackPtr->stack );
- }
-
- }
- /*----------------------------------------------------------------------------------
-
- TMTestIdentityMapping
-
- this routine returns true if the mapping passed to it is the identity mapping.
-
- ----------------------------------------------------------------------------------*/
- Boolean TMTestIdentityMapping( gxMapping * themap )
- {
- Fixed *fixptr;
-
- fixptr = & ( themap->map[ 0 ][ 0 ] );
-
- return( ( *fixptr++ == ff( 1 ) ) &&
- ( *fixptr++ == ff( 0 ) ) &&
- ( *fixptr++ == ff( 0 ) ) &&
-
- ( *fixptr++ == ff( 0 ) ) &&
- ( *fixptr++ == ff( 1 ) ) &&
- ( *fixptr++ == ff( 0 ) ) &&
-
- ( *fixptr++ == ff( 0 ) ) &&
- ( *fixptr++ == ff( 0 ) ) &&
- ( *fixptr == fract1 )
- );
- }
- /*----------------------------------------------------------------------------------
-
- TMTestPerspectiveShape
-
- this routine returns true if the mapping for a shape has perspective.
-
- ----------------------------------------------------------------------------------*/
- Boolean TMTestPerspectiveShape( gxShape sh )
- {
- Fixed *fixptr;
- gxMapping themap;
-
- fixptr = (Fixed *) GXGetShapeMapping( sh, &themap );
-
- return( ( fixptr[ 2 ] != 0 ) ||
- ( fixptr[ 5 ] != 0 ) );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMBoundsToPoints
-
- this routine takes a rectangle and makes four points out of them.
-
- -------------------------------------------------------------------------------*/
- void TMBoundsToPoints( gxPoint boxp[], const gxRectangle *box )
- {
- boxp[ 0 ].x = boxp[ 1 ].x = box->left;
- boxp[ 0 ].y = boxp[ 2 ].y = box->top;
- boxp[ 2 ].x = boxp[ 3 ].x = box->right;
- boxp[ 1 ].y = boxp[ 3 ].y = box->bottom;
- }
- /*-------------------------------------------------------------------------------
-
- TMPointsToBounds
-
- this routine takes four points and makes a rectangle.
-
- -------------------------------------------------------------------------------*/
- void TMPointsToBounds( gxRectangle *box, const gxPoint *boxp )
- {
- Fixed scratch;
-
- scratch = boxp[ 0 ].x; // left
- if( boxp[ 1 ].x < scratch ) scratch = boxp[ 1 ].x;
- if( boxp[ 2 ].x < scratch ) scratch = boxp[ 2 ].x;
- if( boxp[ 3 ].x < scratch ) scratch = boxp[ 3 ].x;
- box->left = scratch;
-
- scratch = boxp[ 0 ].y; // top
- if( boxp[ 1 ].y < scratch ) scratch = boxp[ 1 ].y;
- if( boxp[ 2 ].y < scratch ) scratch = boxp[ 2 ].y;
- if( boxp[ 3 ].y < scratch ) scratch = boxp[ 3 ].y;
- box->top = scratch;
-
- scratch = boxp[ 0 ].x; // right
- if( scratch < boxp[ 1 ].x ) scratch = boxp[ 1 ].x;
- if( scratch < boxp[ 2 ].x ) scratch = boxp[ 2 ].x;
- if( scratch < boxp[ 3 ].x ) scratch = boxp[ 3 ].x;
- box->right = scratch;
-
- scratch = boxp[ 0 ].y; // bottom
- if( scratch < boxp[ 1 ].y ) scratch = boxp[ 1 ].y;
- if( scratch < boxp[ 2 ].y ) scratch = boxp[ 2 ].y;
- if( scratch < boxp[ 3 ].y ) scratch = boxp[ 3 ].y;
- box->bottom = scratch;
- }
-
-
- /*-------------------------------------------------------------------------------
-
- TMCombineBitmapColors
-
- this routine applies the effect of a transfer mode to a bitmap. NOTE it
- leaves the ink on the shape the same as the original shape.
-
- sh -> the shape which is the bitmap that we need to apply the
- colors to.
- shink -> the ink for the shape which it had originally.
- stackPtr -> a list of transfer modes which are to be applied to the
- shape in addition to the one in shink.
- boxptr -> if not nil then only make a bitmap which occupies this
- bounds. the box is in device space.
- listPtr -> use this stack of transforms to interpret the space
- of the boxptr in shape space.
- -------------------------------------------------------------------------------*/
-
- gxShape TMCombineBitmapColors( gxShape sh, gxInk shink, TTModeStack *stackPtr,
- gxRectangle *boxptr, TTransformList *listPtr )
- {
- OSErr status;
-
- gxBitmap thebits;
- gxPoint where;
-
- check( GXGetShapeType( sh ) == gxBitmapType );
-
- (void) GXGetBitmap( sh, &thebits, &where );
-
- // firgure out if this shape has a color set or direct data
-
- if( ( thebits.space == gxIndexedSpace ) && ( thebits.set != nil ) )
- {
- Handle tempHdl;
- gxSetColor *setptr;
- long setcount;
- long setindx;
-
- gxColor tempcolor;
- gxColorSpace tempspace;
-
- tempcolor.profile = nil;
-
- // make a new shape and a new color set which has the transfer mode applied to it
-
- setindx = setcount = GXGetColorSet( thebits.set, &tempcolor.space, nil );
-
- if( 0 < setindx )
- {
- gxInk tempink = GXCopyToInk( nil, shink );
-
- tempHdl = NewHandle( setcount * sizeof( gxSetColor ) );
- nrequire_action( status = MemError(), TempColorSetFailed, sh = GXCloneShape( sh ); );
-
- HLock( tempHdl );
-
- setptr = * (gxSetColor **) tempHdl;
-
- (void) GXGetColorSet( thebits.set, &tempspace, setptr );
-
- do
- {
- tempcolor.space = tempspace;
-
- * ((TTMColorValues *) &tempcolor.element ) = * ((TTMColorValues *)setptr);
-
- GXSetInkColor( tempink, &tempcolor );
-
- TMCombineColors( &tempcolor, tempink, stackPtr );
-
- GXConvertColor( &tempcolor, gxRGBSpace, nil, nil );
-
- * ((TTMColorValues *) setptr) = * ((TTMColorValues *) &tempcolor.element );
-
- setptr += 1;
-
- } while( 0 < --setindx );
-
- // fix the pointer to the color set
-
- setptr = * (gxSetColor **) tempHdl;
-
- thebits.set = GXNewColorSet( gxRGBSpace, setcount, setptr );
-
- HUnlock( tempHdl );
- DisposeHandle( tempHdl );
-
- GXDisposeInk( tempink );
-
- GXSetBitmap( sh = GXCopyToShape( nil, sh ), &thebits, &where );
- GXSetShapeInk( sh, shink = GXNewInk() );
-
- GXDisposeInk( shink );
- GXDisposeColorSet( thebits.set );
- }
- }
- else if( thebits.space != gxIndexedSpace )
- {
- gxShape sh2;
- gxShape full;
-
- offscreen os;
-
- gxInk saveink;
- gxTransform savetransform;
- gxMapping tempmap;
- gxColor tempcolor;
-
- // we need to create an offscreen bitmap and re-render the bitmap into it
- // also, for every ink in the resolver stack we need to apply the bitmap to
-
- // make a new bitmap but don't copy the bits
-
- sh2 = TMGetBitmapPart( sh, boxptr, listPtr, &where );
-
- CreateOffscreen( &os, sh2 );
- TMAdjustOffscreenDevice( &os, &where );
-
- // we first need to make a white shape and draw it to the offscreen. then
- // we draw the bitmap into the offscreen using the ink that is passed in
-
- full = GXNewShape( gxFullType );
- GXSetShapeTransform( full, os.xform ); // make sure that this draws offscreen
- GXSetShapeColor( full, TMMakeWhite( &tempcolor ) );
-
- // ## for every DrawShape below we need to make sure that gx graphics gives up time
- // ## if not we'll get everyone and their brother screaming at us
-
- GXDrawShape( full ); // this clears the offscreen
-
- // now draw our bitmap into the offscreen with the transfer mode that we were given
-
- saveink = GXCloneInk( GXGetShapeInk( sh ) );
- GXSetShapeInk( sh, shink );
- savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
- GXSetShapeTransform( sh, os.xform );
-
- GXDrawShape( sh ); // blits the given bitmap into the offscreen with the tm
-
- GXSetShapeInk( sh, saveink ); GXDisposeInk( saveink );
- GXSetShapeTransform( sh, savetransform ); GXDisposeTransform( savetransform );
-
- // now we need to apply all of the transfer modes which are on the stack already
-
- if( stackPtr != nil )
- {
- short indx;
- TTModeBlock *blockPtr;
-
- check( 0 < stackPtr->mark );
-
- indx = stackPtr->mark - 1; // these are the number of inks on the stack
-
- HLock((Handle) stackPtr->stack );
-
- blockPtr = & (* stackPtr->stack)[ indx ];
-
- for( ; indx >= 0; --indx )
- {
- GXSetShapeInk( full, blockPtr->tm );
- GXDrawShape( full );
-
- blockPtr -= 1;
- }
-
- HUnlock((Handle) stackPtr->stack );
- }
-
- GXDisposeShape( full );
- DisposeOffscreen( &os );
-
- GXSetShapeMapping( sh2, GXGetShapeMapping( sh, &tempmap ) );
-
- sh = sh2; // this is the shape that we return
- }
-
- TempColorSetFailed:
- return( sh );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMGetBitmapPart
-
- this routine sets up a bitmap record in preparation for redering a part of
- if offscreen.
-
- -------------------------------------------------------------------------------*/
- gxShape TMGetBitmapPart( gxShape sh, gxRectangle *bbox, TTransformList *listPtr, gxPoint *where )
- {
- gxRectangle localbbox;
-
- gxBitmap thebits;
- gxPoint where2;
- gxShape sh2;
-
- gxMapping newmap;
-
- GXGetBitmap( sh, &thebits, &where2 );
-
- if( bbox != nil )
- {
- if( listPtr != nil && TMGetDeviceMapping( &newmap, sh, listPtr ) )
- {
- gxPoint corners[ 4 ];
- gxMapping invmap;
-
- InvertMapping( &invmap, &newmap );
- TMBoundsToPoints( corners, bbox );
- MapPoints( &invmap, 4, corners );
- TMPointsToBounds( &localbbox, corners );
- }
- else
- {
- localbbox = *bbox;
- }
-
- #define FixedFloor( x ) ((long) (x) & 0xFFFF0000)
- #define FixedCeiling( x ) ((long) ((x) + 0xFFFF) & 0xFFFF0000)
-
- where2.x = localbbox.left;
- where2.y = localbbox.top;
-
- // the reson for rounding here is to >> by 16 -- the floor and ceiling deal with the frac part
-
- thebits.width = FixedRound( FixedCeiling( localbbox.right ) - FixedFloor( localbbox.left ) );
- thebits.height = FixedRound( FixedCeiling( localbbox.bottom ) - FixedFloor( localbbox.top ) );
-
- check( thebits.width > 0 );
- check( thebits.height > 0 );
-
- #undef FixedFloor
- #undef FixedCeiling
- }
-
- thebits.image = nil;
- thebits.pixelSize = 32;
- thebits.space = gxRGB32Space;
- thebits.set = nil;
- thebits.profile = nil;
- thebits.rowBytes = 0;
-
- // ## at some point when we need to take the resolution of the device
- // ## into account so that we can set up the mapping in the shape well
-
- sh2 = GXNewBitmap( &thebits, &where2 );
-
- *where = where2;
-
- return( sh2 );
-
- }
-
- /*-------------------------------------------------------------------------------
-
- TMGetDeviceMapping
-
- this routine concatenates all of the mapping on the stack and returns
- a mapping which when applied to a set of points will map them from shape
- space into device space. the mapping can be inverted to obtain a maping
- which goes from device space to shape space.
-
- -------------------------------------------------------------------------------*/
-
- Boolean TMGetDeviceMapping( gxMapping *newmap, gxShape sh, TTransformList *listptr )
- {
- gxMapping themap;
- gxTransform *trptr;
-
- short indx;
- Boolean usemapping;
-
- (void) GXGetShapeMapping( sh, newmap );
-
- if( 0 <= ( indx = listptr->mark - listptr->top - 1 ) ) // a zero based count of the transforms
- {
- check( 0 <= indx );
-
- trptr = & (* listptr->list)[ listptr->mark - 1 ];
-
- // the next step is to the the clip's mapping into device space
-
- for( ; indx >= 0; --indx )
- {
- GXGetTransformMapping( *trptr, &themap );
- MapMapping( newmap, &themap );
-
- trptr -= 1;
- }
-
- usemapping = true;
- }
- else
- {
- usemapping = ( TMTestIdentityMapping( newmap ) ) ? false : true;
- }
-
- return( usemapping );
- }
-
- /*-------------------------------------------------------------------------------
-
- TMResolveBitmap
-
- this routine takes a shape stack which is currently pointed to a bitmap and
- produces a bitmap that has the transfer modes resolved on it. this routine
- also can take a stack of transfer modes which it will apply to the shape
- after it is done rendering all of the other shapes into it.
-
- stackPtr -> the stack pointer which contains all of the shapes.
- tmPtr -> a list of transfer modes which need to be applied
- to the bitmap after we are all done rendering offscreen.
- boxptr -> only render this part of the shape (in device space).
-
- -------------------------------------------------------------------------------*/
- gxShape TMResolveBitmap( TShapeStack *stackPtr, TTModeStack *tmPtr, gxRectangle *boxptr )
- {
- gxPoint where;
-
- gxShape sh;
- gxShape full;
- gxColor tempcolor;
-
- offscreen os;
-
- long count;
-
- TRNABlock rna;
-
- check( 0 < stackPtr->index );
-
- sh = TMGetBitmapPart( stackPtr->sh, boxptr, nil, &where );
-
- CreateOffscreen( &os, sh );
- TMAdjustOffscreenDevice( &os, &where );
-
- full = GXNewShape( gxFullType );
- GXSetShapeTransform( full, os.xform );
- GXSetShapeColor( full, TMMakeWhite( &tempcolor ) );
-
- GXDrawShape( full );
-
- count = stackPtr->index;
-
- TMFreeShape( stackPtr );
- TMRewindStack( stackPtr );
-
- do
- {
- gxShape sh2;
-
- rna.root = nil;
- rna.branch = nil;
- rna.node = nil;
- rna.seed = 0;
-
- TMAttachShape( &rna, TMNextShape( stackPtr ), nil, stackPtr );
-
- if( rna.root != nil )
- sh2 = GXCloneShape( rna.root );
- else
- sh2 = GXNewPicture( 1, &rna.node, &rna.rootst, &rna.roottm, &rna.roottr );
-
- GXSetShapeTransform( sh2, os.xform );
-
- GXDrawShape( sh2 ); // this draws it offscreen
-
- GXDisposeShape( sh2 );
-
- if( rna.root != nil )
- {
- GXDisposeShape( rna.root );
- }
- else
- {
- GXDisposeShape( rna.node );
-
- if( rna.rootst != nil ) GXDisposeStyle( rna.rootst );
- if( rna.roottm != nil ) GXDisposeInk( rna.roottm );
- if( rna.roottr != nil ) GXDisposeTransform( rna.roottr );
- }
-
- } while( stackPtr->index < count );
-
- // when we get here the stack is pointing to the bitmap shape again
-
- if( tmPtr != nil )
- {
- short indx;
- TTModeBlock *blockPtr;
-
- // we now have to apply all of the transfer modes which are on the stack
-
- check( 0 < tmPtr->mark );
-
- indx = tmPtr->mark - 1; // these are the number of inks on the stack
-
- HLock((Handle) tmPtr->stack );
-
- blockPtr = & (* tmPtr->stack)[ 0 ];
-
- for( ; indx >= 0; --indx )
- {
- GXSetShapeInk( full, blockPtr->tm );
- GXDrawShape( full );
-
- blockPtr += 1;
- }
-
- HUnlock((Handle) tmPtr->stack );
- }
-
- // finally compute the clip for this shape
-
- {
- TTransformList *listptr = &stackPtr->tr;
-
- gxRectangle bounds;
- gxShape clip;
- gxShape other;
-
- gxTransform *trptr;
-
- gxMapping map;
-
- short indx;
-
- GXGetShapeBounds( stackPtr->sh, 0, &bounds ); // the original bitmap on the stack
- clip = GXNewRectangle( &bounds );
-
- other = GXGetShapeClip( stackPtr->sh );
- GXIntersectShape( clip, other );
- GXDisposeShape( other );
-
- GXGetShapeMapping( stackPtr->sh, &map );
- GXMapShape( clip, &map );
-
- // walk the transform list and come up with a clip for this shape
-
- if( 0 <= ( indx = listptr->mark - listptr->top - 1 ) ) // a zero based count of the transforms
- {
- check( 0 <= indx );
-
- trptr = & (* listptr->list)[ listptr->mark - 1 ];
-
- // the next step is to the the clip's mapping into device space
-
- for( ; indx >= 0; --indx )
- {
- other = GXGetTransformClip( *trptr );
- GXIntersectShape( clip, other );
- GXDisposeShape( other );
-
- GXGetTransformMapping( *trptr, &map );
- GXMapShape( clip, &map );
-
- trptr -= 1;
- }
- }
-
- GXSetShapeClip( sh, clip );
- GXDisposeShape( clip );
- }
-
- GXDisposeShape( full );
- DisposeOffscreen( &os );
-
- return( sh );
-
- }
- /*-------------------------------------------------------------------------------
-
- TMMakeWhite
-
- this routine takes a color data structure and fills it in with white.
-
- -------------------------------------------------------------------------------*/
- gxColor *TMMakeWhite( gxColor *colorptr )
- {
- colorptr->space = gxRGBSpace;
- colorptr->profile = nil;
- colorptr->element.rgb.red = 0xFFFF;
- colorptr->element.rgb.green = 0xFFFF;
- colorptr->element.rgb.blue = 0xFFFF;
-
- return( colorptr );
- }
-